home *** CD-ROM | disk | FTP | other *** search
- /* ======================== X10CTRL.C ================================= */
- /* (c) 1988, Stephen L. Childress. 818/706-5247
-
- Main Program.
-
- Amiga 500/1000/2000 program to manage the X10 USA, Inc. CP290
- computer interface ($35). This device connects to an Amiga (or other computer)
- via an RS232 serial port. With this software, the user can establish
- on/off/dim events of a specified duration for specific days of the week.
- This is done by drawing lines on a graphics screen with the mouse.
- Having done so, this event data can be down-loaded to the CP290 box.
- From this point, the CP290 will perform the event data forever, without
- further help from the Amiga.
-
- This software also enables the user to up-load the event data to the
- Amiga, view it on the graphics screen, and save it to disk. Lastly, the
- user can issue an immediate X10 command to an X10 module, from the
- Amiga keyboard.
-
-
- Makefile: (Lattice C)
-
- x10ctrl: x10ctrl.o x10struct.o
- blink TO x10ctrl FROM lib:c.o x10ctrl.o x10struct.o \
- LIB lib:lc.lib lib:amiga.lib
-
- x10ctrl.o: x10ctrl.c x10ctrl.h
- lc x10ctrl.c
-
- x10struct.o: x10struct.c x10ctrl.h
- lc x10struct.c
-
-
-
-
- *******************************************************/
-
-
-
- #include <exec/types.h>
- #include <exec/exec.h>
- #include <dos.h>
- #include <graphics/view.h>
- #include <graphics/display.h>
- #include <intuition/intuition.h>
- #include <devices/serial.h>
- #include <stdio.h>
- #include "x10ctrl.h"
-
- char * stpchr();
- UWORD * ColorTableAddr;
- struct ColorMap *ColorMapAddr;
- struct ViewPort *ViewPortAddr(), *vpa;
- extern USHORT colortable[];
-
- char datafilename[64], scratchbuf[64];
-
- extern struct Gadget /* see X10STRUCT.C */
- gadNAME,
- gadFROMX10,
- gadX10COMMAND,
- gadSECURITY,
- gadNEWFILE,
- gadWEEKEND,
- gadWEEKDAYS,
- gadSUN,
- gadSAT,
- gadFRI,
- gadTHURS,
- gadWED,
- gadTUES,
- gadMON,
- gadSETNAME,
- gadDIMUP,
- gadDIMDN,
- gadOFF,
- gadON,
- gadX10DATE,
- gadTOX10,
- gadNEXT,
- gadDEL,
- gadQUIT,
- gadSETBASE,
- gadEARLIER,
- gadLATER,
- gadLONGER,
- gadSHORTER;
-
- extern struct IntuiText
- savemsgbody,
- savemsgyes,
- savemsgno,
- ynmessage,
- yesmsg,
- nomsg,
- gadNAMEmsg;
-
- extern struct StringInfo nameinfo;
-
-
- /*** Things related to the serial port: ***/
-
- extern struct MsgPort *CreatePort();
- struct IOExtSer IORser; /* Serial port IO request block */
- int Serialisopen = 0;
-
-
-
- /** beware of changing this! */
- int minutesK = 60 / HourSpacing; /* pixels per minute */
-
-
- #if 0
-
- /* ================================================================= */
- /* This table has the time of sunset for the 1st day of each month.
- The times are GMT standard time, 24hr notation, e.g., 1800 = 6PM.
- Taken from a 1984 almanac. The times are for 30 degrees North Latitude.
- */
-
- SHORT sunsettable[] = {
- /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
- 1711, 1737, 1800, 1819, 1837, 1856, 1905, 1853, 1822, 1745, 1713, 1700
- };
-
- /* Table of corrections, by month, for sunset, to account for Daylight Savings
- time. This table assumes Daylight Savings is practiced. */
- SHORT dsmonths[] = {
- 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0
- };
- #endif
-
-
-
-
- /* ================================================================= */
-
- struct Events {
- USHORT
- link,
- xstart,
- xstop;
- UBYTE
- devicecode,
- days,
- command,
- dimness,
- flags;
- } Events[recordlimit+1];
-
-
- int devicelist[deviceMax+1];
-
- int mousex,
- mousey,
- xmax,
- Devnum,
- devicey,
- Eventnum = 0,
- oldx,
- gadPspacing = gadCspacing * charwidth,
- infoline = gadline-3,
- infowidth = 79 - infocol,
- error,
- Signalflag,
- Changed = 0,
- DevAreaY,
- infox,
- infoy,
- Daymask = 0x7f,
- BaseHouseCode = 1,
- yesyesflag,
- verbose = VERBOSE; /* see the .h */
-
- int clas, code;
-
- UBYTE X10cmd[256];
-
- char textbuf[256];
-
- struct Window *sbwindow = NULL;
- struct Window *window, *OpenWindow(); /* returns ptr to structure */
- struct Screen *screen, *OpenScreen();
-
- struct IntuiMessage *GetMsg(), *Message;
- struct IntuitionBase *IntuitionBase;
- struct IntuiText intuitext;
-
- char days[8][4] = { {"__"},{"M "},{"Tu"},{"W "},{"Th"},{"F "},{"Sa"},{"Su"} };
-
- char bsr[6][8] = { {"NONE"}, /* 0 these correspond to bsrON, bsrOFF... */
- {"NONE"}, /* 1 */
- {"ON "}, /* 2 */
- {"OFF "}, /* 3 */
- {"NONE"}, /* 4 */
- {"DIM "} }; /* 5 */
-
- /* This table is indexed 0..n for housecode 1..16 to
- yield the X10 version of that housecode. So housecode=2 ('B') = hex E0 */
- UBYTE Housecodes[] = { 0x00,
- 0x60, 0xE0, 0x20, 0xA0,
- 0x10, 0x90, 0x50, 0xD0,
- 0x70, 0xF0, 0x30, 0xB0,
- 0x00, 0x80, 0x40, 0xC0 }; /* see pg 10 of X10 manual */
-
-
- char devicenames[deviceMax+1][DEVNAMELEN];
-
-
- struct RastPort *Rport,
- *sbRport = NULL;
- struct MsgPort *Intuiport;
- struct AreaInfo ainfo;
-
- PLANEPTR myplane;
- #define TMPRASX 640 /* see AllocRas() herein */
- #define TMPRASY 32
-
- struct GfxBase *GfxBase;
-
- APTR Intuimsg; /* see call to GetMsg() herein */
-
- FILE *datafp;
-
- char nwname[] = " Computerized Home Control Manager for the X10 CP290.";
-
- struct NewScreen X10screen =
- {
- 0, 0, SCREENMAXX, SCREENMAXY, /* size of screen */
- 4, /* depth */
- PENTEXT1, CYAN, /* pens */
- HIRES | INTERLACE | SPRITES,
- CUSTOMSCREEN,
- NULL, /* font */
- (UBYTE *) nwname,
- NULL, /* gadgets */
- NULL /* custom bit map */
- };
-
-
- struct NewWindow nw =
- {
- 0,0, /* LeftEdge and TopEdge */
- SCREENMAXX, SCREENMAXY, /* Width and Height */
- PENTEXT1, BLACK, /* DetailPen and BlockPen */
- /* IDCMP Flags with Flags below */
- CLOSEWINDOW | REFRESHWINDOW | MOUSEBUTTONS | GADGETUP,
-
- WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | ACTIVATE | REPORTMOUSE,
- #if 1
- &gadQUIT, NULL, /* Gadget and Image pointers */
- #else
- NULL, NULL, /* Gadget and Image pointers */
- #endif
- nwname,
- NULL, /* Screen ptr null (this screen) */
- NULL, /* BitMap pointer */
- SCREENMAXX, SCREENMAXY, /* MinWidth and MinHeight */
- SCREENMAXX, SCREENMAXY, /* MaxWidth and MaxHeight */
- CUSTOMSCREEN /* Type of window */
- };
-
-
- struct NewWindow nw1 =
- {
- 50, 50, /* LeftEdge and TopEdge */
- nw1X, nw1Y, /* Width and Height */
- PENTEXT1, BLACK, /* DetailPen and BlockPen */
- /* IDCMP Flags with Flags below */
- CLOSEWINDOW | REFRESHWINDOW | MOUSEBUTTONS | GADGETUP,
-
- WINDOWCLOSE | SMART_REFRESH | ACTIVATE,
- &gadNAME, NULL, /* Gadget and Image pointers */
- "Please...", /* Title string */
- NULL, /* Screen ptr null (this screen) */
- NULL, /* BitMap pointer */
- nw1X, nw1Y, /* MinWidth and MinHeight */
- nw1X, nw1Y, /* MaxWidth and MaxHeight */
- CUSTOMSCREEN /* Type of window */
- };
-
- struct NewWindow standbywindow =
- {
- GADx, GADy-8, /* LeftEdge and TopEdge */
- 640-GADx, 400-GADy+8, /* Width and Height */
- GREEN, RED, /* DetailPen and BlockPen */
- /* IDCMP Flags with Flags below */
- REFRESHWINDOW | MOUSEBUTTONS | GADGETUP,
-
- SMART_REFRESH | ACTIVATE,
- NULL, NULL, /* Gadget and Image pointers */
- " B-B-B-BUSY - PLEASE WAIT! ",/* Title string */
- NULL, /* Screen ptr null (this screen) */
- NULL, /* BitMap pointer */
- nw1X, nw1Y, /* MinWidth and MinHeight */
- nw1X, nw1Y, /* MaxWidth and MaxHeight */
- CUSTOMSCREEN /* Type of window */
- };
-
-
- /* ================================================================= */
-
-
-
- int
- main()
- {
- register int i, j, more;
- int n;
- int error, x, x1, days, command, dimness, class, flags;
- register char *p;
- /***
- struct IntuiText *;
- struct Gadget *gad;
- */
-
- /*** Open serial port and set baud rate, etc., for the X10 box.
- */
-
- IORser.io_SerFlags |= SERF_SHARED;
- if ((error = OpenDevice (SERIALNAME, 0, &IORser, 0)) != 0) {
- printf( "Unable to open Serial Device, error=%ld\n", error );
- exit(20);
- }
-
- i = (int)
- (IORser.IOSer.io_Message.mn_ReplyPort = CreatePort("SetSerial", 0));
- if (i == NULL) {
- printf( "Unable to create port for IO message\n" );
- CloseDevice(&IORser);
- exit(20);
- }
- ++Serialisopen;
-
- /*** Read serial port control settings. Then change them to
- the values appropriate for the X10 box.
- */
-
- IORser.IOSer.io_Command = SDCMD_QUERY;
- if (error = DoIO( &IORser ) != 0) {
- printf ( "Query status error %ld\n", error);
- cleanup();
- exit(20);
- }
-
- IORser.io_Baud = 600;
- IORser.io_StopBits = 1;
- IORser.io_WriteLen = 8;
- IORser.io_ReadLen = 8;
- IORser.io_SerFlags = 0;
-
- IORser.io_SerFlags |= SERF_XDISABLED;
-
- IORser.IOSer.io_Command = SDCMD_SETPARAMS;
-
- if (error = DoIO( &IORser) != 0) {
- printf("Serial I/O SETPARAMS error\n");
- cleanup();
- exit(20);
- }
-
- for (i = 1; i <= 16; ++i)
- X10cmd[i] = 0xff; /* build X10 cmd header */
-
- infox = infocol * charwidth;
- infoy = infoline * charwidth;
-
- purge(); /* erase all events, initialize strings, etc. */
-
-
-
-
-
- IntuitionBase =
- (struct IntuitionBase *) OpenLibrary ("intuition.library", 0);
- if (IntuitionBase == NULL) {
- printf("Open Intuition failed\n");
- exit(50);
- }
-
- GfxBase =
- (struct GfxBase *) OpenLibrary ("graphics.library", 0);
- if (GfxBase == NULL) {
- printf("Open graphics failed\n");
- exit(50);
- }
-
- screen = OpenScreen(&X10screen);
- if (screen == NULL) {
- printf("OpenScreen failed\n");
- exit(50);
- }
-
- nw.Screen = screen;
-
- if ((window = OpenWindow(&nw)) == NULL) {
- printf("OpenWindow failed\n");
- cleanup();
- exit(20);
- }
-
-
-
-
- Signalflag = 1 << window->UserPort->mp_SigBit;
- Intuiport = window->UserPort;
- Rport = window->RPort;
-
- /*** vpa = ViewPortAddress(window);
- ColorMapAddr = vpa -> ColorMap;
- ColorTableAddr = (UWORD *) ColorMapAddr -> ColorTable;
- ****/
-
-
- LoadRGB4(ViewPortAddress(window), &colortable[0], 16);
- strcpy(datafilename, DATAFILENAME);
-
-
- top:
-
- purge();
- Eventnum = Devnum = 0;
- TimeGraticule(); /* create gaticule displays */
- hourlines(); /* redraw the hour lines */
- info(0); /* setup blank info window in lower right of screen */
- setdategadgets(); /* turn off all day-of-week gadgets */
- ScreenToFront(screen); /* WB screen requester can push us to the back */
-
-
-
- /*** Reload X10 Event data from ASCII disk file. */
-
- reopen0:
- p = " Event Data Disk File Name (Click CLOSE gadget if none) ? ";
- goto reopen2;
- reopen1:
- p = " Unable to open file. New Name? ";
- reopen2:
- if ((i = getfilename(p)) < 0) {
- cleanup();
- exit(20);
- }
-
- if (i == 1)
- goto reopen0; /* name strlen == 0 */
-
- if (i == 2)
- goto withoutfile; /* user closed the window */
-
-
-
-
- datafp = fopen(datafilename, "r");
- if (datafp == NULL)
- goto reopen1;
-
- more = 1;
- n = 1;
- while (more) {
- /*** note: the intermediate variables, e.g., x and x1 below, had to
- be used as Lattice C did not compute address of (& operator)
- correctly for an array of structures (Events[])
- ***/
-
- i = fscanf(datafp, "%d,%d,%d,%d,%d,%d,%d\n",
- &Devnum,
- &x,
- &x1,
- &days,
- &command,
- &dimness,
- &flags );
- Events[n].devicecode = Devnum;
- Events[n].xstart = x;
- Events[n].xstop = x1,
- Events[n].days = days;
- Events[n].command = command;
- Events[n].dimness = dimness;
- Events[n].flags = flags;
-
-
- if (Devnum > 0 && Devnum <= deviceMax) {
- i = devicelist[Devnum];
- if (i == 0)
- devicelist[Devnum] = n;
- else {
- while (Events[i].link)
- i = Events[i].link;
- Events[i].link = n;
- }
- Events[n].link = 0;
- ++n;
- }
- else {
- --more;
- }
- }
-
- /*** Now read the names of the X10 devices: A5 is Porch light, etc.
- */
-
- more = 2;
-
- while (more && (feof(datafp) == 0) ) {
- if (fgets(textbuf, sizeof(textbuf), datafp) != NULL) {
- stcd_i(textbuf, &n); /* Lattice function: ASCII to int */
- p = stpchr(textbuf, '"');
- if (p != NULL) {
- j = strlen(++p) - 2; /* 2 because of closing " and \n */
- if (j >= DEVNAMELEN)
- j = DEVNAMELEN;
- if (j > 0 && n > 0 && n <= deviceMax) /* if valid device no. */
- strncpy(&devicenames[n], p, j);
- }
- }
- else
- --more;
- }
- fclose(datafp);
-
-
-
-
-
-
-
-
-
- withoutfile:
-
-
- Eventnum = Devnum = 0;
- RenderAllEvents(); /* display graphs for all events */
-
- /* gad = &gadMON;
- for (i = 0; i <= 6; ++i) {
- intuitext = gad->GadgetText;
- intuitext->FrontPen = (UBYTE) ( (~(DAYCOLOR0 + i)) & 15);
- gad = gad->NextGadget;
- }
- ******/
-
-
-
-
- /************************ M A I N L O O P ********************/
-
-
- for ( ;; ) {
- /*** Discard queued up mouse messages */
- while ( (Message = GetMsg(Intuiport)) != 0)
- ReplyMsg(Message);
- SetSignal(0, Signalflag);
-
-
-
- if ((Message = GetMsg(Intuiport)) == 0) { /*** Get a new mouse message */
- Wait(Signalflag);
- Message = GetMsg(Intuiport);
- }
-
- Intuimsg = (APTR)Message->IAddress; /* for gadgets, points to gadget*/
-
- class = Message->Class;
- code = Message->Code;
- mousex = window->MouseX;
- mousey = window->MouseY;
- ReplyMsg(Message);
-
-
- /* ================================================================= */
-
- Daymask = Events[Eventnum].days;
-
- /*** Process mouse action: Gadget or clicked on a pixel */
-
- switch (class) {
-
- case GADGETUP: /* button released on a Gadget */
-
- if (Intuimsg == (APTR)&gadQUIT) { /* "QUIT" */
- goto signoff;
- }
-
- if (Intuimsg == (APTR)&gadFROMX10) { /* UP-LOAD */
- Eventnum = 0;
- if (Changed)
- savedata();
- standby(1);
- if ((n = upload()) != 0) {
- if (n != -1) /* if -1, msg was done by upload() */
- yesyes("Error reading events from CP2910 (X10)");
- }
- ++Changed;
- standby(0);
- break;
- }
-
- if (Intuimsg == (APTR)&gadEARLIER) { /* EARLIER */
- if (Eventnum == 0)
- pleasemodule();
- else {
- x = Events[Eventnum].xstart;
- if (validspan(Eventnum,
- --x, Events[Eventnum].xstop) == 0) {
- RenderOneEvent(-1, Eventnum, NULL);
- Events[Eventnum].xstart = x;
- --Events[Eventnum].xstop;
- RenderOneEvent(RED, Eventnum, NULL);
- info(0);
- ++Changed;
- }
- else
- printf("validspan=%d\n",
- validspan(Eventnum,x, Events[Eventnum].xstop));
- }
- break;
- }
-
- if (Intuimsg == (APTR)&gadLATER) { /* LATER */
- if (Eventnum == 0)
- pleasemodule();
- else {
- x = Events[Eventnum].xstop;
- if (validspan(Eventnum,
- Events[Eventnum].xstart, ++x) == 0) {
- RenderOneEvent(-1, Eventnum, NULL);
- ++Events[Eventnum].xstart;
- Events[Eventnum].xstop = x;
- RenderOneEvent(RED, Eventnum, NULL);
- info(0);
- ++Changed;
- }
- }
- break;
- }
-
-
-
- if (Intuimsg == (APTR)&gadLONGER) { /* LONGER */
- if (Eventnum == 0)
- pleasemodule();
- else {
- x = Events[Eventnum].xstop;
- if (validspan(Eventnum,
- Events[Eventnum].xstart, ++x) == 0) {
- RenderOneEvent(-1, Eventnum, NULL);
- Events[Eventnum].xstop = x;
- RenderOneEvent(RED, Eventnum, NULL);
- info(0);
- ++Changed;
- }
- }
- break;
- }
-
- if (Intuimsg == (APTR)&gadSHORTER) { /* SHORTER */
- if (Eventnum == 0)
- pleasemodule();
- else {
- x = Events[Eventnum].xstop;
- if (validspan(Eventnum,
- Events[Eventnum].xstart, --x) == 0) {
- RenderOneEvent(-1, Eventnum, NULL);
- Events[Eventnum].xstop = x;
- RenderOneEvent(RED, Eventnum, NULL);
- info(0);
- ++Changed;
- }
- }
- break;
- }
-
-
-
- if (Intuimsg == (APTR)&gadTOX10) { /* DOWN-LOAD */
- standby(1);
- if ((n = download()) != 0)
- notresponding(n);
- standby(0);
- break;
- }
-
-
- if (Intuimsg == (APTR)&gadNEXT) { /* "NEXT" */
- if (Eventnum) {
- Eventnum = successor(Eventnum);
- RenderOneDevice(Devnum);
- info(0);
- setdategadgets();
- }
- else
- pleasemodule();
- break;
- }
-
- if (Intuimsg == (APTR)&gadX10COMMAND) { /* X10COMMAND */
- if (Eventnum) {
- standby(1);
- if ((n = x10command()) != 0)
- notresponding(n);
- standby(0);
- }
- else
- pleasemodule();
- break;
- }
-
- if (Intuimsg == (APTR)&gadSETNAME) { /* "SET NAME" */
- if (Eventnum)
- setname();
- else
- pleasemodule();
- break;
- }
-
- if (Intuimsg == (APTR)&gadSETBASE) { /* "SET BASE" */
- if (yesno(" Erases Displayed Events! ")) {
- if (setbase() == 0) { /* get new Basecode */
- purge(); /* erase all */
- Eventnum = 0;
- TimeGraticule();
- info(0);
- setdategadgets();
- }
- }
- break;
- }
-
- if (Intuimsg == (APTR)&gadDEL) { /* "DELETE" */
- if (Eventnum) {
- DeleteEvent(Eventnum);
- info(0);
- setdategadgets();
- }
- else
- pleasemodule();
- break;
- }
-
- if (Intuimsg == (APTR)&gadX10DATE) { /* "SET DATE" */
- standby(1);
- x10date();
- standby(0);
- break;
- }
-
-
- if (Intuimsg == (APTR)&gadON) { /* "ON" */
- if (Eventnum) {
- ++Changed;
- Events[Eventnum].command = bsrON;
- info(0);
- }
- else
- pleasemodule();
- break;
- }
-
- if (Intuimsg == (APTR)&gadOFF) { /* "OFF" */
- if (Eventnum) {
- ++Changed;
- Events[Eventnum].command = bsrOFF;
- info(0);
- }
- else
- pleasemodule();
- break;
- }
-
- if (Intuimsg == (APTR)&gadDIMUP) { /* "BRIGHTER" */
- if (Eventnum) {
- ++Changed;
- Events[Eventnum].command = bsrDIM;
- n = --Events[Eventnum].dimness;
- if (n < 0)
- Events[Eventnum].dimness = 0;
- info(0);
- }
- else
- pleasemodule();
- break;
- }
-
- if (Intuimsg == (APTR)&gadDIMDN) { /* "DIMMER" */
- if (Eventnum) {
- Events[Eventnum].command = bsrDIM;
- ++Changed;
- n = ++Events[Eventnum].dimness;
- if (n >= 16 )
- Events[Eventnum].dimness = 15;
- info(0);
- }
- else
- pleasemodule();
- break;
- }
-
-
- if (Intuimsg == (APTR)&gadNEWFILE) { /* "NEW FILE" */
- if (Changed)
- savedata();
- goto top;
- }
-
- if (Intuimsg == (APTR)&gadSECURITY) { /* "SECURITY" */
- if (Eventnum == 0)
- pleasemodule();
- else {
- Events[Eventnum].flags ^= SECURITY;
- setdategadgets();
- ++Changed;
- }
- break;
- }
-
- if (Eventnum) {
- /* If there is a selected event, and if the
- user clicks on a day-name, then that day's
- enable bit is toggled in the event data. */
-
- if (Intuimsg == (APTR)&gadMON) j = 1;
- else if (Intuimsg == (APTR)&gadTUES) j = 2;
- else if (Intuimsg == (APTR)&gadWED) j = 4;
- else if (Intuimsg == (APTR)&gadTHURS) j = 8;
- else if (Intuimsg == (APTR)&gadFRI) j = 16;
- else if (Intuimsg == (APTR)&gadSAT) j = 32;
- else if (Intuimsg == (APTR)&gadSUN) j = 64;
- else if (Intuimsg == (APTR)&gadWEEKDAYS)j = 0x1F;
- else if (Intuimsg == (APTR)&gadWEEKEND) j = 0x60;
- else j = 0;
-
- if (j) {
- RenderOneEvent(-1, Eventnum, NULL);
- i = Events[Eventnum].days;
- if ((i ^= j) != 0) { /* preclude NO days */
- Events[Eventnum].days = i;
- info(0);
- setdategadgets();
- RenderOneEvent(RED, Eventnum, NULL);
- ++Changed;
- }
- else
- yesyes("That would select NO Days!");
- }
- }
- break;
-
-
-
- case CLOSEWINDOW: /* the system CLOSE WINDOW gadget */
- signoff:
- if (Changed)
- savedata();
- cleanup();
- exit(0);
-
- case MOUSEBUTTONS: /* Not a gadget, clicked on a pixel */
- if (code == SELECTDOWN) { /* Button pressed down? */
- if (mousey <= DevAreaY && mousey >= Yorg) {
- /* clicked in top half, where events are drawn */
-
- if (Eventnum) /* undraw RED one, if any */
- RenderOneEvent(0, Eventnum, devicenames[Devnum]);
-
- i = Devnum; /* previous device # */
- Devnum = (mousey-Yorg) / barsize; /* new device no. */
-
- if (mousex > xmax) { /* clicked on right side? */
- if (i == Devnum)
- Eventnum = successor(Eventnum);
- else
- Eventnum = listhead(Devnum);
- info(0);
- setdategadgets();
- RenderOneEvent(RED,Eventnum,devicenames[Devnum]);
- }
- else if (mousey >= Yorg) {
-
- /* clicked on left side...on an event line? */
- Eventnum = listhead(Devnum);
-
- while (Eventnum)
- if (mousex >= Events[Eventnum].xstart &&
- mousex <= Events[Eventnum].xstop )
- break;
- else
- Eventnum = Events[Eventnum].link;
-
- if (Eventnum == 0)
- AddEvent(); /* another event this dev */
- info(0);
- setdategadgets();
- RenderOneEvent(RED,Eventnum,devicenames[Devnum]);
- }
- }
- }
- break;
-
- default:
- if (Eventnum) {
- RenderOneEvent(0, Eventnum, devicenames[Devnum]);
- setdategadgets();
- info(0);
- Eventnum = Devnum = 0;
- break;
- }
-
- } /* switch */
-
-
- } /* for */
-
- return(0);
- }
-
- /* ================================================================= */
-
- validspan(event, startx, stopx)
- register int event, startx, stopx;
- {
-
- register int n;
- int dev;
-
-
- if (startx > stopx)
- return(-1);
-
- if (stopx > xmax)
- return(-3);
-
- if (startx <= 0)
- return(-5);
-
- n = Events[event].link; /* n = next event, if any */
- if (n)
- if (stopx >= Events[n].xstart)
- return(-7);
-
- dev = Events[event].devicecode; /* find preceeding event, if any */
- n = devicelist[dev];
-
- while (n) {
- if (Events[n].link == event) {
- if (startx <= Events[n].xstop)
- return(-11); /* bumped into left-hand neighbor */
- break; /* it's OK */
- }
- n = Events[n].link;
- }
- return(0);
- }
-
-
-
- /* ================================================================= */
-
-
- pleasemodule()
- {
- yesyes("Please Click On An Event or a Module Number.");
- return(0);
- }
-
-
- /* ================================================================= */
-
- /** This table converts unit number 1..8 or 9..16
- to a bit flag, per X10 manual. Index with (1 <= n <= 8) */
- SHORT unitcode[] = {
- 0, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x1
- };
-
-
- download()
- {
- register int unit, i, n, t;
- int dev, eventnum;
- register char *p;
-
- if (Eventnum)
- RenderOneEvent(0, Eventnum, devicenames[Devnum]); /* unRED display */
- Eventnum = Devnum = 0;
- info(0);
-
- if (Changed)
- savedata();
-
- X10cmd[17] = 0; /* base housecode & reset interface */
- X10cmd[18] = Housecodes[BaseHouseCode]; /* housecode */
- x10out(&X10cmd[1],18);
- if (getack() < 0)
- return(-1);
-
- eventnum = 0;
- purgex10(); /* purge pending input data */
-
- for (dev = 1; dev <= deviceMax; ++dev) { /* usually, 32 devices */
-
- n = devicelist[dev]; /* event number 1..128 */
-
- if (n == 0)
- continue; /* skip all this code for unused dev's */
-
- p = &devicenames[dev][0];
- X10cmd[17] = 3; /* event/graphics download */
-
- for (i = 0; i <= 7; ++i) {
- t = ((dev-1) * 8) + i; /* graphics object # 0..256 */
- X10cmd[18] = t << 1;
- X10cmd[19] = (t >> 7) + 4; /* see page 25 of X10 manual */
- if (*p < 0x20 || *p > 0x7f)
- X10cmd[20] = 0x20;
- else
- X10cmd[20] = *p;
- X10cmd[21] = *++p;
- ++p;
-
- /* if (verbose)
- printf("dnload dev %d's dev name; cmd=%02X %02X %02X %02X %02X\n",
- dev, X10cmd[17],X10cmd[18],X10cmd[19],X10cmd[20],X10cmd[21]);
- */ x10out(&X10cmd[1], 22); /* download 2 chars of devicename */
- /* The controller doesn't ACK this command */
- }
-
- unit = ((dev-1) % 16) + 1;
- t = (dev-1) / 16;
- X10cmd[26] = Housecodes[t + BaseHouseCode];
-
- if (unit <= 8)
- X10cmd[24] = unitcode[dev];
- else
- X10cmd[24] = 0;
- if (unit > 8)
- X10cmd[25] = unitcode[unit - 8];
- else
- X10cmd[25] = 0;
-
- /*** do all events for the current device */
- while (n) {
- sprintf(scratchbuf, "Sending Device #%d, event #%d", dev, n);
- appease(scratchbuf);
-
- /** Compose command for start of event */
- ++eventnum;
- X10cmd[18] = eventnum << 3; /* see pg 21 of X10 manual */
- X10cmd[19] = eventnum >> 5; /* n must be <= 128 */
- if (Events[n].flags & SECURITY)
- X10cmd[20] = 9; /* normal vs. security mode */
- else
- X10cmd[20] = 8;
-
- X10cmd[21] = Events[n].days;
- t = Events[n].xstart * minutesK;
- X10cmd[22] = t / 60; /* hours */
- X10cmd[23] = t % 60; /* minutes */
- X10cmd[27] = (Events[n].dimness << 4) | Events[n].command;
- t = 0;
- for (i = 20; i <= 27; ++i) { /* compute checksum per X10 manual */
- t += X10cmd[i];
- }
- X10cmd[28] = t;
- x10out(&X10cmd[1], 28); /* download this activity */
- if (getack() < 0)
- return(-1);
-
- /*** If event just sent is not an OFF command then
- create and send an OFF command to match the command
- just downloaded. This is because OFF events are not
- stored herein, unless they are special; explicitly defined.
- ***/
-
- if ( (Events[n].command != bsrOFF) ) {
- /*** 6/20/91 ***/
- #if 0
- printf("dev=%d n=%d Events[n].xstop=%d Events[Events[n].link].xstart=%d\n",
- dev, n, Events[n].xstop, Events[Events[n].link].xstart);
- #if 1
- if (Events[n].link &&
- ((Events[Events[n].link].xstart -
- Events[n].xstop) == 1))
- goto ADJACENCY;
- #endif
- #endif
- ++eventnum;
- X10cmd[18] = eventnum << 3;
- X10cmd[19] = eventnum >> 5;
- t = Events[n].xstop * minutesK;
- X10cmd[22] = t / 60; /* hours */
- X10cmd[23] = t % 60; /* minutes */
- X10cmd[27] = bsrOFF;
-
- t = 0;
- for (i = 20; i <= 27; ++i) /* compute checksum per X10 manual */
- t += X10cmd[i];
-
- X10cmd[28] = t;
- x10out(&X10cmd[1], 28); /* download event # n-1 */
- if (getack() < 0)
- return(-1);
- }
- ADJACENCY:
- n = Events[n].link; /* next event, this device */
- } /* while (linked list for dev N) */
- }
- return(0);
- }
-
-
- /* ======== Erase all stored events ============ */
- purge()
- {
- register int i;
-
- Eventnum = Devnum = Changed = 0;
-
- for (i = 0; i <= deviceMax; ++i) {
- devicenames[i][0] = '\0';
- devicelist[i] = 0;
- }
-
- for (i = 0; i <= recordlimit; ++i)
- Events[i].link = Events[i].devicecode = 0;
-
- return(0);
- }
-
-
- /* ======== Retrieve Event Data & Dev. Names From X10 Box ================= */
-
- upload()
- {
- register int i, n, t;
- int dev = 0, eventnum = 1, x10counter = 0;
- int prevcmd = -1, prevdev = -1, thiscmd, thisdev, x10byte, icon;
- UBYTE *p, x10reply[32];
-
- appease("Requesting Data from CP290");
-
- purge(); /* purge all events */
- TimeGraticule();
- info(0);
-
- purgex10(); /* scrub pending serial input */
- X10cmd[17] = 5; /* request events, see page 31 of X10 manual */
- x10out(&X10cmd[1], 17); /* event # n-1 */
- Delay(50);
-
- /*** read and discard leading sync and the status byte */
-
- do {
- if ( (n = x10inbyte()) < 0) {
- notresponding(n);
- return(-1);
- }
- }
- while (n == 0xff); /* "status" is first byte other than 0xff */
-
-
- /*** Read all uploaded events */
-
- while (x10counter++ < 128) {
- if ((n = x10inbyte()) < 0)
- return(-2);
- n &= 0xff;
-
- if (n != 0xff) { /* active event? */
- x10reply[1] = n; /* dupe. 1st byte */
- for (i = 2; i <= 8; ++i) { /* read an event */
- if ((n = x10inbyte()) < 0)
- return(-3);
- x10reply[i] = n & 0xff;
- }
-
- sprintf(scratchbuf, "Receiving event #%d", eventnum);
- appease(scratchbuf);
-
-
- t = (x10reply[5] << 8) + x10reply[6]; /* bit map of unit codes */
- dev = 16;
- while ((t & 1) == 0) {
- --dev;
- if ((t >>= 1) == 0)
- return(-4);
- }
-
- n = x10reply[7]; /* house code */
- for (i = 1; i <= 16; ++i)
- if (n == (int)Housecodes[i])
- break; /* i = 1 If housecode == 0x60, etc. */
- Events[eventnum].devicecode = dev + ((i-1) * 16); /* 1..32 */
-
- if ((x10reply[1] & 0x0F) == 9)
- Events[eventnum].flags |= SECURITY;
- else
- Events[eventnum].flags &= (~SECURITY);
-
- Events[eventnum].dimness = (x10reply[8] >> 4) & 0x0F;
- Events[eventnum].command = (x10reply[8] & 0x0F);
- Events[eventnum].days = x10reply[2];
- n = ((x10reply[3] * 60) + x10reply[4]) / minutesK;
- if (n > xmax)
- return(-5);
- Events[eventnum].xstart = Events[eventnum].xstop = n;
-
- thisdev = Events[eventnum].devicecode;
- thiscmd = Events[eventnum].command;
-
- /*** Throw away this uploaded event if
- 1) It is for same device as previous one, and
- 2) the previous event was NOT an OFF command, and
- 3) the current event IS an OFF event.
- This discards the OFF event paired with some earlier event.
- ***/
-
- if ( (prevdev == thisdev) /* use OFF part of last event */
- && (prevcmd != bsrOFF)
- && (thiscmd == bsrOFF) )
- Events[eventnum -1].xstop = Events[eventnum].xstart;
- else { /* create new event */
- Events[eventnum].link = 0;
- if ((n = devicelist[dev]) == 0)
- devicelist[dev] = eventnum++; /* make head of list */
- else {
- while (Events[n].link)
- n = Events[n].link;
- Events[n].link = eventnum++; /* make tail of list */
- }
- }
- prevdev = thisdev;
- prevcmd = thiscmd;
- }
- }
-
- purgex10(); /* scrub pending serial input */
- X10cmd[17] = 6; /* request graphics data */
- x10out(&X10cmd[1], 17);
- while (x10inbyte() == 0xff) /* discard sync & status */
- ;
-
- for (icon = 1; icon <= 256; ++icon) {
-
- if (((icon-1) & 7) == 0) {
- dev = (icon / 8) + 1;
- sprintf(scratchbuf, "Receiving device name #%d", dev);
- appease(scratchbuf);
- p = &devicenames[dev][0];
- }
- if ((x10byte = x10inbyte()) < 0)
- return(x10byte);
- if (x10byte != 0xff) { /* vacant space? */
- *p++ = x10byte; /* assign 2 bytes */
- *p++ = (char) x10inbyte();
- }
- }
-
- for (dev = 1; dev <= deviceMax; ++dev) /* truncate */
- devicenames[dev][DEVNAMELEN-1] = '\0';
-
- RenderAllEvents();
- info(0);
- setdategadgets();
- return(0);
- }
-
- #if 0
- /* ================================================================= */
-
- sunset()
- {
- register int month, min, hhmm24;
- char clockinfo[8];
-
- getclk(clockinfo); /* See Lattice 4.0 page F110 */
- month = (int)clockinfo[2];
- hhmm24 = sunsettable[month-1] + (dsmonths[month] * 100);
-
- min = (hhmm24 / 100) * 60; /* hour time minutes per hour */
- min += hhmm24 % 60; /* minutes part */
-
- return(min / minutesK); /* time as an offset in pixels along X */
-
- }
- #endif
-
-
- /* ================================================================= */
-
- int
- x10command()
- {
- register int n, m;
-
- X10cmd[17] = 1;
- X10cmd[18] = Events[Eventnum].command;
- X10cmd[18] |= (Events[Eventnum].dimness << 4);
- n = (Events[Eventnum].devicecode -1) / 16;
- X10cmd[19] = Housecodes[n+1];
-
- if ((n = Events[Eventnum].devicecode) == 0) /* device 1..32 */
- return(-2); /* should never be 0! */
- n &= 15; /* n = device 1..16 */
- if (n == 0)
- n = 16;
-
- m = 0x8000; /* see page 12 of X10 manual for bit alignment */
- while (--n)
- m >>= 1;
- X10cmd[20] = m & 0xff;
- X10cmd[21] = m >> 8;
- X10cmd[22] = X10cmd[18] + X10cmd[19] + X10cmd[20] + X10cmd[21];
-
- appease("Sending to CP290");
- x10out(&X10cmd[1], 22);
- n = getack();
- if (n < 0)
- return(0);
- return(0);
- }
-
-
- /* ================================================================= */
- int
- notresponding(err)
- int err;
- {
- char prompt[100];
-
- sprintf(prompt, " The X10 CP290 Controller Is Not Responding! (%d) ", err);
-
- return(yesyes(prompt));
- }
-
- /* ================================================================= */
- int
- getack() /* read the ACK response to a command */
- {
- register int x10reply;
-
- do
- if ((x10reply = x10inbyte()) < 0) {
- notresponding(x10reply);
- return(x10reply);
- }
- while (x10reply == 0xff); /* discard syncs */
- return(x10reply); /* response should be 0 or 1 */
- }
-
-
- /* ================================================================= */
- int
- x10date()
- {
- register int n, x10byte;
- char x10info[8], clockinfo[8], *dayis, basecode;
-
-
- dateagain:
- purgex10();
- X10cmd[17] = 4; /* Request date */
- x10out(&X10cmd[1], 17);
-
- do {
- x10byte = x10inbyte();
- if (x10byte < 0) {
- notresponding(x10byte);
- return(x10byte);
- }
- }
- while (x10byte & 0x80); /* strip leading syncs */
-
- x10info[0] = x10byte; /* status byte */
-
- for (n = 1; n <= 5; ++n) {
- if ((x10byte = x10inbyte()) < 0) {
- notresponding(x10byte);
- return(x10byte);
- }
- x10info[n] = x10byte;
- }
-
- switch ((int)x10info[3]) {
- case 0x40: dayis = "Sun";
- break;
- case 0x20: dayis = "Sat";
- break;
- case 0x10: dayis = "Fri";
- break;
- case 0x08: dayis = "Thu";
- break;
- case 0x04: dayis = "Wed";
- break;
- case 0x02: dayis = "Tue";
- break;
- case 0x01: dayis = "Mon";
- break;
- default: dayis = "???";
- break;
- }
- switch ((int)x10info[4]) {
- case 0x60: basecode = 'A';
- break;
- case 0xE0: basecode = 'B';
- break;
- case 0x20: basecode = 'C';
- break;
- case 0xA0: basecode = 'D';
- break;
- case 0x10: basecode = 'E';
- break;
- case 0x90: basecode = 'F';
- break;
- case 0x50: basecode = 'G';
- break;
- case 0xD0: basecode = 'H';
- break;
- case 0x70: basecode = 'I';
- break;
- case 0xF0: basecode = 'J';
- break;
- case 0x30: basecode = 'K';
- break;
- case 0xB0: basecode = 'L';
- break;
- case 0x00: basecode = 'M';
- break;
- case 0x80: basecode = 'N';
- break;
- case 0x40: basecode = 'O';
- break;
- case 0xC0: basecode = 'P';
- break;
- default: basecode = '?';
- break;
- }
-
- sprintf(textbuf, "DATE: %s, %d:%02d (base-code:%c) - Change to Amiga's DATE?",
- dayis, x10info[2], x10info[1], basecode);
- if (yesno(textbuf)) {
- getclk(clockinfo); /* See Lattice 4.0 page F110 */
- X10cmd[17] = 2; /* set clock */
- X10cmd[18] = clockinfo[5]; /* min */
- X10cmd[19] = clockinfo[4]; /* hr */
- switch ((int)clockinfo[0]) {
- case 0: n = 0x40; /* Sunday */
- break;
- case 1: n = 0x01; /* Mon */
- break;
- case 2: n = 0x02; /* Tue */
- break;
- case 3: n = 0x04; /* Wed */
- break;
- case 4: n = 0x08; /* Thu */
- break;
- case 5: n = 0x10; /* Fri */
- break;
- case 6: n = 0x20; /* Sat */
- break;
- }
- X10cmd[20] = n;
- X10cmd[21] = X10cmd[18] + X10cmd[19] + X10cmd[20]; /* chksum */
- x10out(&X10cmd[1], 21);
- getack();
- goto dateagain;
- }
- return(0);
- }
-
-
-
- /* ================================================================= */
-
- int
- yesno(p)
- char *p;
- {
- register int w, result, save1;
-
-
- save1 = colortable[WHITE];
- colortable[WHITE] = DEEPBLUE;
- LoadRGB4(ViewPortAddress(window), &colortable[0], 16);
-
- ynmessage.IText = p;
- w = (strlen(p) * 8) + 50;
- if (w < 200)
- w = 200;
-
- if (yesyesflag == 0)
- result = AutoRequest(window, &ynmessage, &yesmsg, &nomsg,
- 0, 0, w, 64);
- else
- result = AutoRequest(window, &ynmessage, &yesmsg, &yesmsg,
- 0, 0, w, 64);
-
- colortable[WHITE] = save1;
- LoadRGB4(ViewPortAddress(window), &colortable[0], 16);
- return(result);
- }
-
- /* ================================================================= */
-
- int
- yesyes(p)
- char *p;
- {
- register int result;
-
- ++yesyesflag;
- result = yesno(p);
- yesyesflag = 0;
- return(result);
- }
-
- /* ================================================================= */
- int
- purgex10()
- {
- register int i;
-
- for (i = 1; i <= 2; ++i) {
- Delay(10);
- while (x10inbyte() >= 0)
- ; /* purge pending data */
- }
- return(0);
- }
-
- /* ================================================================= */
-
- int
- x10out(buf, count) /* send a buffer to the X10 CP290 Interface Unit */
- char *buf;
- int count;
- {
- register int n;
- register char *p = buf;
- char emsg[80];
-
- IORser.IOSer.io_Command = CMD_WRITE;
-
- for (n = count; n > 0; --n) {
- IORser.IOSer.io_Data = (APTR)p++;
- IORser.IOSer.io_Length = 1;
- if (error = DoIO(&IORser)) {
- sprintf(emsg, "Serial Port WRITE error %d", error)
- yesyes(emsg);
- return(error);
- }
- Delay(1); /* X10 says delay between bytes (this is 1/50 of a sec) */
- }
- return(0);
- }
-
- /* ================================================================= */
-
-
- static char onech;
-
- int
- x10inbyte() /* returns < 0 if error, else 8 bit reply data */
- {
- register int n, timeout = 5;
- char prompt[100];
-
- reread:
- chkabort();
- IORser.IOSer.io_Command = SDCMD_QUERY; /* See if data is available */
- if ((n = DoIO(&IORser)) != 0) {
- sprintf(prompt, " Serial Port Read Error: %d ", n);
- yesyes(prompt);
- return(-1);
- }
- if (IORser.IOSer.io_Actual != 0) {
- IORser.IOSer.io_Command = CMD_READ;
- IORser.IOSer.io_Length = 1;
- IORser.IOSer.io_Data = (APTR)&onech;
- if (DoIO(&IORser) != 0)
- return(-2); /* return if I/O error */
- }
- else {
- Delay(5); /* No data avail now, so delay and retry */
- if (--timeout > 0)
- goto reread;
- return(-3);
- }
- n = onech & 255;
- if (verbose)
- printf("$%02X ",n);
- return(n);
- }
-
- /* ================================================================= */
-
-
- int
- standby(on) /* prompt user to wait before taking next action */
- int on;
- {
-
- if (on) {
- standbywindow.Screen = screen;
- if ((sbwindow = OpenWindow(&standbywindow)) == NULL)
- return(-1);
- sbRport = sbwindow->RPort;
- }
- else if (sbwindow != NULL) {
- CloseWindow(sbwindow);
- sbwindow = NULL;
- sbRport = NULL;
- }
- return(0);
- }
-
-
- /* ================================================================= */
- #define APPEASEMSGX 200
- #define APPEASEMSGY 50
-
- appease(msg)
- char *msg;
- {
- char buf[80];
-
- if (sbRport == NULL)
- return(-1);
-
- SetAPen(sbRport, GREY8);
- intuitext.IText = buf;
- intuitext.FrontPen = GOLD;
- intuitext.DrawMode = JAM2;
-
-
- sprintf(buf, " %-40s ", msg);
- PrintIText(sbRport, &intuitext, APPEASEMSGX, APPEASEMSGY);
-
- return(0);
-
- }
-
- /* ================================================================= */
-
- int
- setname()
- {
-
- nameinfo.Buffer = (UBYTE *)&devicenames[0];
- strcpy(nameinfo.Buffer, &devicenames[Devnum]);
- nameinfo.MaxChars = DEVNAMELEN;
-
- if (requeststring(" Name of Appliance? "))
- return(-1);
- if (strlen(nameinfo.Buffer) == 0)
- return(0);
-
- RenderOneEvent(-1, devicelist[Devnum], devicenames[Devnum]); /* erase old string */
- strcpy(&devicenames[Devnum], &devicenames[0]);
- RenderOneEvent(RED, Eventnum, devicenames[Devnum]);
- ++Changed;
- return(0);
- }
-
- /* ================================================================= */
-
- int
- setbase()
- {
- char housechar[2];
-
- housechar[0] = BaseHouseCode-1 + 'A';
- housechar[1] = '\0';
-
- nameinfo.Buffer = (UBYTE *)&housechar;
- nameinfo.MaxChars = 2;
- nameinfo.BufferPos = 1;
- nameinfo.Buffer[0] = housechar[0];
-
- if (requeststring(" Base House Code? "))
- return(-1);
- if (strlen(nameinfo.Buffer) == 0)
- return(-1);
- housechar[0] = toupper(housechar[0]);
-
- if (housechar[0] < 'A' || housechar[0] > 'P')
- return(-1);
- BaseHouseCode = 1 + (housechar[0] - 'A');
- return(0);
- }
-
-
- /* ================================================================= */
-
- int
- requeststring(prompt)
- char *prompt;
- {
- register struct Window *window1;
- register struct MsgPort *intuiport;
- register struct IntuiMessage *message;
- register int signalflag;
- APTR intuimsg;
- int n, class, code;
-
- gadNAMEmsg.IText = prompt;
- nw1.Screen = screen;
- n = (strlen(prompt) * 10);
- if (n < nw1X)
- n = nw1X;
- nw1.Width = n+16;
-
- nameinfo.BufferPos = strlen(nameinfo.Buffer);
-
- if ((window1 = OpenWindow(&nw1)) != NULL) {
- ActivateGadget(&gadNAME, window1, NULL);
- intuiport = window1->UserPort;
- signalflag = 1 << window1->UserPort->mp_SigBit;
- Wait(signalflag);
- message = GetMsg(intuiport);
-
- intuimsg = (APTR)message->IAddress; /* for gadgets, points to gadget*/
-
- class = message->Class;
- code = message->Code;
- ReplyMsg(message);
- CloseWindow(window1);
-
- if (class == CLOSEWINDOW)
- return(-1);
- }
- return(0);
- }
-
-
- /* ================================================================= */
-
- int
- getfilename(prompt)
- /* return: 0=have name; 1=blank name; 2=closed window; -1=abort requested */
- char *prompt;
- {
-
- nameinfo.Buffer = scratchbuf;
- strcpy(nameinfo.Buffer, datafilename);
- nameinfo.MaxChars = sizeof(datafilename)-1;
-
- /* get filename string. if user clicks on window close, ask QUIT? */
- if (requeststring(prompt)) {
- if (yesno(" QUIT? "))
- return(-1); /* yes, abort */
- else
- return(2); /* no, don't quit, but don't have a name */
- }
-
- if (strlen(nameinfo.Buffer) == 0)
- return(1); /* name length bad? */
-
- strcpy(datafilename, nameinfo.Buffer);
- return(0);
- }
-
- /* ================================================================= */
-
-
- int
- savedata()
- {
- register int dev, n;
-
- FILE *datafp = NULL;
-
-
- while (datafp == NULL) {
- if (yesno("Write Screen's Info. Into a File? ") == 0)
- return(1);
-
- if ((n = getfilename(" What file? ")) != 0)
- return(n);
-
- datafp = fopen(datafilename, "w");
- }
-
-
- for (dev = 1; dev <= deviceMax; ++dev) {
- n = devicelist[dev];
- while (n) {
- fprintf(datafp, "%d,%d,%d,%d,%d,%d,%d\n",
- Events[n].devicecode,
- Events[n].xstart,
- Events[n].xstop,
- Events[n].days,
- Events[n].command,
- Events[n].dimness,
- Events[n].flags);
-
- n = Events[n].link;
- }
- }
- fprintf(datafp, "0,0,0,0,0,0,0\n");
-
- for (dev = 1; dev <= deviceMax; ++dev)
- if (devicenames[dev][0] != '\0')
- fprintf(datafp, "%d,\"%s\"\n", dev, &devicenames[dev]);
-
- fclose(datafp);
- Changed = 0;
- return(0);
- }
-
-
-
- /* =================================================================
- set the displayed day-of-week gadgets (MON, TUE...) to the On/Off
- state as stored in the currently active event's "days" item. */
-
-
- setdategadgets()
- {
- register struct Gadget *gad;
- register int i, daybits;
-
-
- gad = &gadMON; /* start of gadget list */
- Daymask = daybits = Events[Eventnum].days;
-
- for (i = 1; i <= 64; i *= 2) { /* each day ... */
- setonegad(gad, (i & daybits) );
- gad = gad->NextGadget;
- }
-
- setonegad(&gadSECURITY, Events[Eventnum].flags & SECURITY);
- return(0);
- }
-
-
- /* ================================================================= */
-
- setonegad(g, on)
- struct Gadget *g;
- int on;
- {
- register int oldsel, newsel;
-
-
- oldsel = g->Flags;
- if (on)
- newsel = SELECTED;
- else
- newsel = 0;
-
- g->Flags |= SELECTED;
- if (oldsel != newsel)
- RefreshGList(g, window, NULL, 1);
- if (newsel == 0)
- g->Flags &= (~SELECTED);
- return(0);
- }
-
-
-
- /* ================================================================= */
-
-
-
- int
- info(device) /* display info for a given device code */
- int device;
- {
- register int i, m, n;
- int x, y,
- t1,t2,
- cmd,
- color,
- eventdays,
- lnum = infoline+1;
- char *p, *p1, dimmsg[8];
-
- SetBPen(Rport, BLACK);
-
- Daymask = Events[Eventnum].days;
-
- if (device == 0) {
- if (Devnum == 0)
- n = 0;
- else
- n = devicelist[Devnum]; /* use currently selected one */
- }
- else
- n = devicelist[device]; /* use caller's selected one */
-
- /*** Print days of week, with Currently selected day(s) in PENTEXT1 */
-
- p = "MTWTFSS";
- x = infocol * charwidth;
- y = (lnum -1) * charwidth;
-
- for (i = 1; i <= 64; i *= 2) {
- SetAPen(Rport, Daymask & i ? RED : GREEN);
- Move(Rport, x, y);
- Text(Rport, p++, 1);
- x += 8;
- }
-
-
- /*** Print all events ocurring on the selected day(s) */
-
- while (n) {
- p = &textbuf[0];
- if (n != Eventnum)
- color = GREEN;
- else
- color = RED;
- m = i = 1;
- x = infocol * charwidth;
- y = ((lnum -1) * charwidth) +1;
- eventdays = Events[n].days;
-
- /*** Draw a box for those days of the week
- that the event is active */
-
- while (i <= 0x40) {
- if (eventdays & i)
- SetAPen(Rport, DAYCOLOR0 + m - 1);
- else
- SetAPen(Rport, BLACK);
- RectFill(Rport, x+2, y+2, x+6, y+6);
- x += 8;
- i *= 2;
- ++m;
- }
-
- /*** This code displays the start/stop times for an event */
-
- SetAPen(Rport, color);
- t1 = Events[n].xstart * minutesK;
- t2 = Events[n].xstop * minutesK;
- cmd = Events[n].command;
-
- if (cmd == bsrDIM)
- sprintf(p1 = dimmsg, "%2d", 16 - Events[n].dimness);
- else
- p1 = " ";
-
- sprintf(p, " %02d:%02d\-%02d:%02d %s%s",
- t1 / 60, t1 % 60, t2 / 60, t2 % 60, bsr[cmd], p1);
- Move(Rport, x+8, lnum * charwidth);
- Text(Rport,textbuf,strlen(p));
- ++lnum;
- n = Events[n].link;
- }
-
- /*** Erase to end of screen */
-
- SetAPen(Rport, BLACK);
- RectFill(Rport, infocol * charwidth, ((lnum-1) * charwidth) +1, 638, 398);
- return(0);
- }
-
- /* ================================================================= */
-
-
- int
- DeleteEvent(eventno)
- int eventno;
- {
- register int n;
-
- if (eventno == 0) {
- pleasemodule();
- return(-1);
- }
- ++Changed;
-
- n = devicelist[Devnum]; /* n = head of list */
- RenderOneEvent(-1, eventno, NULL); /* erase RED event */
-
- if (n == eventno) {
- if (Events[eventno].link == 0) { /* deleteing sole member of list? */
- RenderOneEvent(0, eventno, devicenames[Devnum]); /* unRED dev name */
- RenderOneEvent(-1, eventno, NULL); /* erase event */
- }
- devicelist[Devnum] = Events[eventno].link; /* delete at head of list*/
- }
- else {
- while (Events[n].link != eventno) { /* find predecessor event */
- if (n == 0) {
- yesyes("Predecessor link error");
- cleanup();
- exit(1); /* corrupted list */
- }
- n = Events[n].link;
- }
- Events[n].link = Events[eventno].link; /* delete within list */
- }
- Eventnum = successor(Events[eventno].link); /* update selected event no. */
- Events[eventno].devicecode = 0; /* mark node as unused */
-
- if (Eventnum == 0)
- Eventnum = listhead(Devnum);
- if (Eventnum)
- RenderOneDevice(Devnum); /* put new RED on display */
- hourlines();
- return(0);
- }
-
- /* ================================================================= */
-
-
- int
- AddEvent()
- {
- register int n;
- int t, predn, xlimit;
- register int node, x;
-
- ++Changed;
- node = 0;
-
- while (Events[++node].devicecode != 0)
- ; /* nothing, find an unused node */
-
- Events[node].devicecode = Devnum;
- Events[node].xstart = mousex;
- Events[node].xstop = mousex;
- Events[node].link = 0;
- Events[node].command = bsrON;
- Events[node].days = 0x7F;
- Events[node].flags = 0;
-
- Eventnum = node;
-
- xlimit = xmax;
- x = mousex;
- n = devicelist[Devnum]; /* head of list */
- predn = 0;
-
- while (n) { /* find non-overlapping limit for this event */
- t = Events[n].xstart;
- if (xlimit > t && x < t)
- xlimit = t -1;
- predn = n;
- n = Events[n].link;
- }
-
-
- if (n == devicelist[Devnum]) { /* empty list or insert at head of list */
- Events[node].link = n;
- devicelist[Devnum] = node;
- }
- else { /* insert within list */
- t = Events[predn].link;
- Events[predn].link = node;
- Events[node].link = t;
- }
-
- RenderOneEvent(RED, node, devicenames[Devnum]);
-
- do {
- if (x - window->MouseX) {
- RenderOneEvent(-1, node, NULL);
- x = window->MouseX;
- if (x < Events[node].xstart)
- x = Events[node].xstart;
- if (x > xlimit)
- x = xlimit;
- Events[node].xstop = x;
- RenderOneEvent(RED, node, NULL);
- }
- Delay(1);
- }
- while ((SetSignal(0,0) & Signalflag) == 0); /* mouse button UP Message */
-
- Wait(Signalflag);
- Message = GetMsg(Intuiport);
- ReplyMsg(Message);
- hourlines();
- return(0);
- }
-
- /* ================================================================= */
-
-
- int
- RenderAllEvents()
- {
- register int i;
-
- for (i = 1; i <= deviceMax; ++i)
- RenderOneDevice(i);
- info(0);
- return(0);
- }
-
-
-
-
- /* ================================================================= */
- int
- RenderOneDevice(devno)
- {
- register int j, h, e;
-
- e = 0;
- h = j = devicelist[devno];
-
-
- while (j) {
- if (j == Eventnum)
- e = j;
- RenderOneEvent(0, j, NULL);
- j = Events[j].link;
- }
-
- if (e)
- RenderOneEvent(RED, e, devicenames[devno]); /* draw red one last! */
- else
- RenderOneEvent(0, h, devicenames[devno]); /* show name */
- return(0);
- }
-
- /* ================================================================= */
-
- int
- RenderOneEvent(color, event, name) /* draw event lines for active days */
- int color, event;
- char *name;
- {
- register int y, day, dayflag, eventdays;
- int device;
-
- if (event == 0)
- return(-1);
-
- /* show the device name in proper color */
-
- device = Events[event].devicecode - 1; /* device no. 0..n */
- y = ((device+1) * barsize) + Yorg;
-
- if (color <= 0)
- intuitext.FrontPen = DEVNAMECOLOR; /* normal color */
- else
- intuitext.FrontPen = color; /* could be RED or TIMEFILLCOLOR */
-
- if (name) { /* if head of list */
- intuitext.IText = textbuf;
- intuitext.DrawMode = JAM1;
- sprintf(textbuf, "%c%d %s",
- ('A'-1)+BaseHouseCode+(device/16), (device & 15) + 1, name);
- PrintIText(Rport, &intuitext, xmax+1, y);
- }
-
-
- if (color < 0) {
- SetAPen(Rport, TIMEFILLCOLOR);
- RectFill(Rport, Events[event].xstart, y, Events[event].xstop, y+6);
- return(0);
- }
-
- dayflag = 1;
- eventdays = Events[event].days;
-
- for (day = 0; day < 7; ++day) {
- if (eventdays & dayflag) {
- if (color >= 0)
- SetAPen(Rport, color ? color : DAYCOLOR0 + day);
- Move(Rport, Events[event].xstart, y+day);
- Draw(Rport, Events[event].xstop, y+day);
- }
- dayflag *= 2;
- }
- return(0);
- }
-
- /* ================================================================= */
-
- /*** Draw the regions for the events for each X10 device
- and show the device name as found in the disk file */
-
- int
- TimeGraticule()
- {
- register int device, x, y;
-
-
- DevAreaY = (deviceMax * barsize) + Yorg; /* smaller numbers are dev area */
-
- /* Erase the event display area of screen */
- xmax = HourSpacing * 24;
- SetAPen(Rport, BLACK);
- RectFill(Rport, 8,Yorg, nw.MaxWidth-2, DevAreaY);
-
- /* Draw horizontal box for each possible X10 device # and
- print the textual name of each device, as found in the data file. */
-
- intuitext.FrontPen = DEVNAMECOLOR;
- intuitext.DrawMode = JAM1;
- intuitext.IText = &textbuf[0];
- for (device = 0; device < deviceMax; ++device) {
- y = ((1+device) * barsize) + Yorg;
- SetAPen(Rport, TIMEFILLCOLOR);
- RectFill(Rport, 2, y, nw.MaxWidth, y+barheight);
- sprintf(textbuf, "%c%d %s",
- ('A'-1)+BaseHouseCode+(device/16),
- (device & 15) + 1, &devicenames[device+1]);
- PrintIText(Rport, &intuitext, xmax+1, y);
- }
-
-
- /* Draw AM/PM legends on display */
- y = DevAreaY + 16;
- intuitext.FrontPen = TIMELINECOLOR;
- intuitext.IText = "AM";
- PrintIText(Rport, &intuitext, 0, y);
- intuitext.IText = "PM";
- PrintIText(Rport, &intuitext, 13*HourSpacing, y);
- intuitext.IText = "N";
- PrintIText(Rport, &intuitext, (12 * HourSpacing) + 2, y);
-
-
- x = 12 * HourSpacing;
- SetAPen(Rport,TIMELINECOLOR);
- Move(Rport, 20, y+4);
- Draw(Rport, x-2, y+4);
- Move(Rport, 14 * HourSpacing, y+4);
- Draw(Rport, 24 * HourSpacing, y+4);
- hourlines(); /* add the vertical hour lines */
-
- return(0);
- }
-
- /* ================================================================= */
-
- /*** Draw 24 lines vertically, depicting 24 hours/day */
- static int hrlineflag = 1;
-
- int
- hourlines()
- {
- register int y, hour, x, hh;
-
- intuitext.IText = &textbuf[0];
- intuitext.FrontPen = TIMELINECOLOR;
- intuitext.DrawMode = JAM1;
-
- y = DevAreaY + 10;
- x = 0;
- hh = 0;
-
- for (hour = 0; hour <= 24; ++hour) {
- SetAPen(Rport, TIMELINECOLOR);
- Move(Rport, x, barsize);
- Draw(Rport, x, y);
- if (hrlineflag && hh) {
- sprintf(textbuf, "%2d", hh);
- PrintIText(Rport, &intuitext, x - 8, y);
- }
- x += HourSpacing;
- if (++hh > 12)
- hh = 1;
- }
- hrlineflag = 0;
- return(0);
- }
-
- /* ================================================================= */
-
- /*** Terminate program housekeeping */
-
- int
- cleanup()
- {
- if (myplane)
- FreeRaster(myplane,TMPRASX,TMPRASY);
- if (window)
- CloseWindow(window);
- if (screen)
- CloseScreen(screen);
- if (IntuitionBase)
- CloseLibrary(IntuitionBase);
- if (GfxBase)
- CloseLibrary(GfxBase);
- if (Serialisopen) {
- DeletePort( IORser.IOSer.io_Message.mn_ReplyPort );
- CloseDevice( &IORser );
- }
-
-
- return(0);
- }
-
- /* ================================================================= */
-
- /* return next in list for given day mask */
-
- successor(eventno)
- int eventno;
- {
- register int n;
-
- if ( (n = Events[eventno].link) == 0)
- return(listhead(Events[eventno].devicecode));
-
- #ifdef DAYMASK
- while ( (Events[n].days & Daymask) == 0)
- if ( (n = Events[n].link) == 0)
- break;
- #endif
- return(n);
- }
-
- /* ================================================================= */
-
- /* Return 1st in list for given day mask */
- listhead(devno)
- int devno;
- {
- register int n;
-
-
- n = devicelist[devno];
-
- #ifdef DAYMASK
- while (n)
- if (Events[n].days & Daymask)
- break;
- else
- n = Events[n].link;
- #endif
- return(n);
- }